package org.zjvis.datascience.web.controller.knowledgeGraph;

import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.vo.konwledgeGraph.constructionVO.*;
import org.zjvis.datascience.service.kg.KnowledgeGraphService;

import javax.validation.Valid;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

@RequestMapping("/knowledge/graph")
@RestController
@Validated
public class KnowledgeGraphConstructionController {
    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    @Value("${restful.knowledgeGraphConstruct.url:#{null}}")
    private String KG_SERVICE_API;
    private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient.Builder().build();
    @Autowired
    private KnowledgeGraphService knowledgeGraphService;

    @PostMapping("/save")
    public ResponseEntity<String> addGraph(@Valid @RequestBody KnowledgeGraphConstructionVO knowledgeGraphConstructionVO
    ) throws IOException {
        if (knowledgeGraphConstructionVO.getOwner() == null) {
            knowledgeGraphConstructionVO.setOwner(JwtUtil.getCurrentUserId());
        }
        if(knowledgeGraphConstructionVO.getId()==null&&knowledgeGraphConstructionVO.getForm()==null){
            knowledgeGraphConstructionVO.setForm(new ArrayList<>());
        }
        knowledgeGraphConstructionVO.setUser(JwtUtil.getCurrentUserDTO().getName());
        okhttp3.RequestBody formBody = okhttp3.RequestBody.create(MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE), OBJECT_MAPPER.writeValueAsBytes(knowledgeGraphConstructionVO));
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "save")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/delete")
    public ResponseEntity<String> delete(@Valid @RequestBody KnowledgeGraphConstructionVO knowledgeGraphConstructionVO
    ) throws IOException {
        okhttp3.RequestBody formBody = okhttp3.RequestBody.create(MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE), OBJECT_MAPPER.writeValueAsBytes(knowledgeGraphConstructionVO));
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "delete")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @GetMapping("/id")
    public ResponseEntity<String> queryGraphById(@RequestParam Long id
    ) throws IOException {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("id", String.valueOf(id));
            Response response = knowledgeGraphService.queryKGByGet(params, "id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/project-id")
    public ResponseEntity<String> queryGraphByProjectId(@RequestParam Long projectId
    ) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("projectId", String.valueOf(projectId));
            Response response = knowledgeGraphService.queryKGByGet(params, "project-id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/project-id/information")
    public ResponseEntity<String> queryGraphBinformationyProjectId(@RequestParam Long projectId
    ) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("projectId", String.valueOf(projectId));
            Response response = knowledgeGraphService.queryKGByGet(params, "project-id/information");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/edit-time")
    public ResponseEntity<String> queryGraphEditTime(@RequestParam Long id
    ) throws IOException {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("id", String.valueOf(id));
            Response response = knowledgeGraphService.queryKGByGet(params, "edit-time");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/edit-editor")
    public ResponseEntity<String> queryGraphEditEditor(@RequestParam Long id
    ) throws IOException {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("id", String.valueOf(id));
            Response response = knowledgeGraphService.queryKGByGet(params, "edit-editor");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @PostMapping("/relation/instance/save")
    public ResponseEntity<String> saveRelationInstance(@Valid @RequestBody RelationInstanceAndIndividualAndKGVO relationInstanceAndIndividualAndKGVO
    ) throws IOException {
        okhttp3.RequestBody formBody = okhttp3.RequestBody.create(MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE), OBJECT_MAPPER.writeValueAsBytes(relationInstanceAndIndividualAndKGVO));
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "relation/instance/save")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/relation/instance/delete")
    public ResponseEntity<String> deleteRelationInstance(@Valid @RequestBody RelationInstanceDeleteVO relationInstanceDeleteVO
    ) throws IOException {
        okhttp3.RequestBody formBody = okhttp3.RequestBody.create(MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE), OBJECT_MAPPER.writeValueAsBytes(relationInstanceDeleteVO));
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "relation/instance/delete")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @GetMapping("/relation/instance/id")
    public ResponseEntity<String> queryRelationInstance(@RequestParam Long knowledgeGraphId, @RequestParam String id
    ) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", id);
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/instance/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/relation/instance/all")
    public ResponseEntity<String> queryAllRelationInstance(@RequestParam Long knowledgeGraphId
    ) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/instance/all");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @PostMapping("/cache/file/upload")
    public ResponseEntity<String> uploadFile(@RequestParam("uploadFile") MultipartFile file
    ) {
        try {
            Response response = knowledgeGraphService.
                    queryNebulaFile("cache/file/upload", file);
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/cache/file/{id}")
    @ResponseBody
    public ResponseEntity<InputStreamSource> getFile(@PathVariable String id)
            throws IOException {
        Map<String, String> queryParam = new ConcurrentHashMap<>();
        Response response = knowledgeGraphService.queryKGByGet(queryParam, String.format("cache/file/%s", id));
        return ResponseEntity
                .status(response.code())
                .body(
                        new InputStreamResource(response.body().byteStream())
                );
    }

    @GetMapping("/cache/file/name/{id}")
    @ResponseBody
    public ResponseEntity<String> getFileName(@PathVariable String id)
            throws IOException {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            Response response = knowledgeGraphService.queryKGByGet(params, String.format("cache/file/name/%s", id));
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/delete/relation/is-used")
    @ResponseBody
    public ResponseEntity<String> isRelationUsedByIndividual(@RequestParam Long knowledgeGraphId,
                                                             @RequestParam String id)
            throws IOException {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", id);
            Response response = knowledgeGraphService.queryKGByGet(params, "delete/relation/is-used");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @PostMapping("/relation/delete")
    public ResponseEntity<String> deleteRelation(@RequestBody DeleteRelationVo deleteRelationVo) throws IOException {
        okhttp3.RequestBody formBody = okhttp3.RequestBody.create(MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE), OBJECT_MAPPER.writeValueAsBytes(deleteRelationVo));
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "relation/delete")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/relation/save")
    public ResponseEntity<String> saveRelationInfo(@RequestBody SaveRelationVo saveRelationVo) throws IOException {
        okhttp3.RequestBody formBody = okhttp3.RequestBody.create(MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE), OBJECT_MAPPER.writeValueAsBytes(saveRelationVo));
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "relation/save")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @GetMapping("/relation/id")
    public ResponseEntity<String> findRelationById(@RequestParam Long knowledgeGraphId,
                                                   @RequestParam String id) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", id);
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/relation/all")
    public ResponseEntity<String> findAllRelations(@RequestParam Long knowledgeGraphId,
                                                   @RequestParam Long pageNumber,
                                                   @RequestParam Long pageSize) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("pageNumber", String.valueOf(pageNumber));
            params.put("pageSize", String.valueOf(pageSize));
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/all");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/relation/name")
    public ResponseEntity<String> findAllRelations(@RequestParam Long knowledgeGraphId,
                                                   @RequestParam String name,
                                                   @RequestParam Long pageNumber,
                                                   @RequestParam Long pageSize) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("pageNumber", String.valueOf(pageNumber));
            params.put("pageSize", String.valueOf(pageSize));
            params.put("name", String.valueOf(name));
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/name");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/relation/name/respond/name")
    public ResponseEntity<String> findRelationsNameByName(@RequestParam Long knowledgeGraphId,
                                                          @RequestParam String name,
                                                          @RequestParam Long pageNumber,
                                                          @RequestParam Long pageSize) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("pageNumber", String.valueOf(pageNumber));
            params.put("pageSize", String.valueOf(pageSize));
            params.put("name", String.valueOf(name));
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/name/respond/name");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/relation/parents")
    public ResponseEntity<String> findParentRelations(@RequestParam Long knowledgeGraphId,
                                                      @RequestParam String id) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(id));
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/parents");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/relation/parents/respond/name")
    public ResponseEntity<String> findParentRelationsName(@RequestParam Long knowledgeGraphId,
                                                          @RequestParam String name) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("name", String.valueOf(name));
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/parents/respond/name");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/relation/children")
    public ResponseEntity<String> findSubRelations(@RequestParam Long knowledgeGraphId,
                                                   @RequestParam String id) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(id));
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/children");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/relation/children/respond/name")
    public ResponseEntity<String> findSubRelationsName(@RequestParam Long knowledgeGraphId,
                                                       @RequestParam String id) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(id));
            Response response = knowledgeGraphService.queryKGByGet(params, "relation/children/respond/name");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }
}
